package org.fdy.common.framework.config;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.util.TypeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.fdy.common.core.units.JacksonUtil;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.*;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;

/**
 * <p>说明：全局返回处理 </P>
 *
 * @author: fangdayang
 * @create: 2023-10-20 00:20
 **/
@Slf4j
@Configuration
@EnableAutoConfiguration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class JacksonConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("JacksonConfig init....");
        converters.forEach(wrapperObjectMapper());
    }

    /**
     * 包装 MappingJackson2HttpMessageConverter
     *
     * @return Consumer
     */
    public static Consumer<HttpMessageConverter<?>> wrapperObjectMapper() {
        return converter -> {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter httpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
                JacksonUtil.initObjectMapper(httpMessageConverter.getObjectMapper());
            }
        };
    }

    @Bean
    @ConditionalOnBean(name = "requestMappingHandlerAdapter")
    public Converter<String, Date> dateConverter() {
        return source -> {
            if (StringUtils.isEmpty(source)) {
                return null;
            } else if (NumberUtil.isLong(source)) {
                return new Date(TypeUtils.castToLong(source));
            } else {
                return DateUtil.parseDate(source);
            }
        };
    }


    @Bean
    @ConditionalOnBean(name = "requestMappingHandlerAdapter")
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return source -> {
            if (StringUtils.isEmpty(source)) {
                return null;
            } else if (NumberUtil.isLong(source)) {
                return LocalDateTime.ofInstant(Instant.ofEpochMilli(TypeUtils.castToLong(source)), ZoneId.systemDefault());
            } else {
                return DateUtil.parse(source).toLocalDateTime();
            }
        };
    }

    @Bean
    @ConditionalOnBean(name = "requestMappingHandlerAdapter")
    public Converter<String, LocalDate> localDateConverter() {
        return source -> {
            if (StringUtils.isEmpty(source)) {
                return null;
            } else if (NumberUtil.isLong(source)) {
                return Instant.ofEpochMilli(TypeUtils.castToLong(source)).atOffset(ZoneOffset.of("+8")).toLocalDate();
            } else {
                return DateUtil.parse(source).toLocalDateTime().toLocalDate();
            }
        };
    }
}
